package types

import (
	"encoding/json"
	//"fmt"
	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"
	"reflect"
	"strings"
)

func Json2H(str interface{}) H {

	temp := H{}

	switch reflect.TypeOf(str).String() {
	case "string":
		return H{"@this": str.(string)}
	case "types.H":
		temp = str.(H)
	case "map[string]interface {}":
		jsonStr, _ := json.Marshal(str)
		return H{"@this": string(jsonStr)}
	default:

	}

	return temp

}

type H map[string]interface{}

func (s H) String() string {
	jsonStr, _ := json.Marshal(s)
	result := string(jsonStr)
	if strings.HasPrefix(result, `{"@this":`) && strings.HasSuffix(result, `}`) {
		temp := gjson.Parse(result).Get("\\@this")
		if temp.Type.String() == "String" {
			return gjson.Parse(temp.String()).String()
		}
		return temp.String()
	}
	return result
}

func (s *H) Get(path string, v ...interface{}) gjson.Result {
	result := gjson.Parse(s.String()).Get(path)
	if result.Exists() {
		return result
	} else {
		if len(v) == 1 {
			temp := H{"default": v[0]}
			return gjson.Parse(temp.String()).Get("default")
		}
		return result
	}
}

func (s *H) SetRaw(path, value string) (string, error) {
	jsonStr, error := sjson.SetRaw(s.String(), path, value)
	if error == nil {
		/**s = make(H)
		error = json.Unmarshal([]byte(jsonStr), &s)*/
		*s = gjson.Parse(jsonStr).Get("@this").Value().(map[string]interface{})
	}
	return jsonStr, error
}

func (s *H) Set(path string, value interface{}) error {

	jsonStr, error := sjson.Set(s.String(), path, value)
	if error == nil {
		// *s = make(H)
		// error = json.Unmarshal([]byte(jsonStr), &s)
		*s = gjson.Parse(jsonStr).Get("@this").Value().(map[string]interface{})
	}
	return error
}
